import pymysql
from Note import *
from preprocess import *
from feature import *
import numpy as np
from itertools import chain

# define constant path
genres = "Jazz Pop Rock Other".split(" ")
MIDI_PATH = "/mnt/dachuang/midi"

# connect mysql
connection = pymysql.connect(
    host="10.60.185.74",
    port=3306,
    user="root",
    password="1112343Jm",
    db="song_similarity"
)

cursor = connection.cursor()
sql = "insert into song_feature(genre, name, song_key, song_mode, chord_num, chord_type, bpm, beat, avg_velocity, avg_duration, duration_type)" \
      "  values(%s, %s, %s, %s, %s, %s, %s, %s ,%s, %s, %s)"


def read_midi(genre):
    for root, dirs, file in os.walk(os.path.join(MIDI_PATH, genre)):
        if len(file) != 0:
            for f in file:
                if f.endswith(".mid"):
                    yield os.path.join(root, f)


def harmony(path):
    preprocessing_machine = preprocessing()
    preprocessing_machine.parsing(path)

    chords = []
    for item in preprocessing_machine.chords:
        chords.append(music21.chord.Chord(item).commonName)

    return len(chords), len(set(chords))


def avg_velocity(music):
    velocity, length = 0, 0
    for instrument in music.instruments:
        length += len(instrument.notes)
        ve = np.array([note.velocity for note in instrument.notes])
        velocity += np.sum(ve)

    velocity /= length
    return format(velocity, '.4f')


def duration(music):
    durations = []
    for instrument in music.instruments:
        durations.extend([note.end - note.start for note in instrument.notes])

    duration = np.sum(durations) / len(durations)
    return format(duration, '.4f'), len(set(durations))

try:
    data = []
    cursor.execute("select name from song_feature")
    song = list(chain.from_iterable(cursor.fetchall()))
    for genre in genres:
        for midi in read_midi(genre):
            try:
                if midi.split("/")[-1] not in song:
                    print(midi)
                    piece = converter.parse(midi)
                    key = piece.analyze("key")
                    key = notes[key.tonic.name], 0 if key.mode == 'minor' else 1
                    chord = harmony(midi)
                    music = pretty_midi.PrettyMIDI(midi)
                    time_signature = music.time_signature_changes[0]
                    other = format(music.estimate_tempo() / 400, '.4f'), format(time_signature.numerator / time_signature.denominator, '.4f'), \
                            avg_velocity(music), *duration(music)
                    example =(genre, midi.split("/")[-1]) + key + chord + other
                    data.append(example)
                    cursor.execute(sql, example)
                    connection.commit()
                    print(midi)
            except Exception:
                continue

    cursor.executemany(sql, data)
    connection.commit()
except Exception:
    print("Exception")












